package com.xiaoming.module1.factory;

import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/***
 * 使用反射生成对象
 *
 * 任务一： 读取、解析XML，通过反射技术实例化对象、存储(Map)
 * 任务二：对外提供获取实例化对象的接口（根据ID）
 */
public class BeanFactory {
    // 存储对象
    private static Map<String, Object> map = new HashMap<>();

    // 执行任务一
    static {
        // 加载xml
        InputStream inputStream = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml");
        // 解析xml
        SAXReader saxReader = new SAXReader();
        try {
            Element root = saxReader.read(inputStream).getRootElement();
            // xpath表达式
            List<Element> beans = root.selectNodes("//bean");
            for (Element bean : beans) {
                String id = bean.attributeValue("id");
                String classPath = bean.attributeValue("class");
                Class<?> aClass = Class.forName(classPath);
                Object o = aClass.getDeclaredConstructor().newInstance();
                map.put(id, o);
            }
            // 维护对象依赖关系
            // 有property
            List<Element> properties = root.selectNodes("//property");
            for (Element property : properties) {
                String name = property.attributeValue("name");
                String ref = property.attributeValue("ref");
                String parentId = property.getParent().attributeValue("id");
                Object parent = getBean(parentId);
                // 遍历父对象，找到set方法
                Method[] methods = parent.getClass().getDeclaredMethods();
                for (Method method : methods) {
                    if (method.getName().equalsIgnoreCase("set" + name)) {
                        method.invoke(parent, getBean(ref));
                    }
                }
                // 重置parent
                map.put(parentId, parent);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 实现任务二
    public static Object getBean(String id) {
        return map.get(id);
    }
}
